
import datetime
import thread
from utils import *

class Game:
    type = 'null game'
    
    def __init__(self, name, server=None):
        self.name = name
        self.server = server
        self.mutex = thread.allocate_lock()
        self.donerecv = thread.allocate_lock()
        self.donerecv.acquire()
        self.donesend = thread.allocate_lock()
        self.message = {}
        self.recd = 0
        self.sent = 0
        self.players = {}
        self.playermsg = {}
        self.open = True
        self.aborted = False
        self.log = {} # (turn,playername):message
        self.turn = 0
        self.sendhandle()
        
    def is_open(self):
        self.lock()
        op = self.open
        self.unlock()
        return op
    
    def lock(self):
        self.mutex.acquire()
        return
    def unlock(self):
        self.mutex.release()
        return
    def locked(self):
        return self.mutex.locked()
    
    def abort(self):
        self.lock()
        hadaborted = self.aborted
        self.aborted = True
        self.unlock()
        if self.server is not None and hadaborted:
            self.server.lock()
            self.server.endgame(self.name)
            self.server.unlock()
        return
    
    def joinhandle(self, name, role):
        '''
        handles a player wanting to join
        
        should be redone by implementors.
        '''
        return True
    def recvhandle(self, name, message):
        '''
        handles a player's message
        
        should be redone by implementors.
        '''
        self.playermsg[name] = message #default, no processing
        return
    def sendhandle(self):
        '''
        prepares self.message to be sent to players.
        
        return true if continuing, false if finishing game.
        
        should be redone by implementors.
        '''
        for pname in self.players:
            self.message[pname] = '{asdf}'
        return True
    
    def playerjoin(self, name, role):
        '''
        
        shall perform locking on its own.
        
        returns True if ok, False if not.
        
        '''
        self.lock()
        if (self.aborted or
            name in self.players):
            self.unlock()
            return False
        r = self.joinhandle(name, role)
        if r:
            self.players[name]=role
        self.unlock()
        return r
    
    def playermessage(self, name, message):
        self.lock()
        if self.aborted:
            self.unlock()
            raise hell
        if name != 'observer':
            self.log[(self.turn,name)]=message
        self.unlock()
        self.donesend.acquire()
        self.donesend.release()
        self.lock()
        if self.aborted:
            self.unlock()
            raise hell
        self.recvhandle(name, message)
        self.recd += 1
        if self.recd >= len(self.players):
            self.donesend.acquire()
            self.donerecv.release()
            self.recd = 0
        self.unlock()
        return
    
    def getmessage(self, name):
        self.lock()
        if self.aborted:
            self.unlock()
            raise hell
        self.unlock()
        self.donerecv.acquire()
        self.donerecv.release()
        self.lock()
        if self.aborted:
            self.unlock()
            raise hell
        self.sent += 1
        if self.sent >= len(self.players):
            self.sent = 0
            self.donerecv.acquire()
            if self.donesend.locked():
                self.donesend.release()
        if self.sent <= 1:
            r = self.sendhandle()
            if not r:
                pass #end log here
        m = self.message[name]
        self.unlock()
        return m
    

import pursuit

game_type_map = {
    'pursuitv0.0' : pursuit.Pursuit,
    }

def newgame(name, type, server=None):
    '''
    todo: have dictionary of game types to games
    '''
    g = game_type_map[type](name, server)
    return g
